package com.xtpt.disaster.service.impl;

import com.alibaba.fastjson.JSON;
import com.xtpt.disaster.bean.JobDetail;
import com.xtpt.disaster.bean.NodeInfo;
import com.xtpt.disaster.bean.TaskInfo;
import com.xtpt.disaster.common.File.ClientAgentUrlGenerator;
import com.xtpt.disaster.common.File.FileCmdBuilder;
import com.xtpt.disaster.common.PortalResult;
import com.xtpt.disaster.common.SQLServer.CallbackUrlGenerator;
import com.xtpt.disaster.common.consts.DataTypeEnum;
import com.xtpt.disaster.common.consts.StatusConst;
import com.xtpt.disaster.service.FileRecoverService;
import com.xtpt.disaster.service.JobDetailService;
import com.xtpt.disaster.service.NodeInfoManageService;
import com.xtpt.disaster.utils.IDGenerator;
import com.xtpt.disaster.utils.LogUtil;
import com.xtpt.disaster.utils.ShellExec;
import com.xtpt.disaster.utils.TimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Logger;

/**
 * @author jack_xin
 * @ClassName FileRecoverServiceImpl
 * @Desc 文件恢复服务
 * @date 2021年12月02日 9:51
 * @Version TODO
 */
@Service
public class FileRecoverServiceImpl implements FileRecoverService {
    @Autowired
    JobDetailService jobDetailService;

    @Autowired
    JobDetail jobDetail;

    @Autowired
    NodeInfoManageService nodeInfoManageService;

    @Autowired
    FileCmdBuilder fileCmdBuilder;

    @Autowired
    ClientAgentUrlGenerator agentUrlGenerator;

    @Autowired
    CallbackUrlGenerator generator;

    /**
     * @Author jack xin
     * @Method Name fileRecover
     * @Desc 使用openssh进行文件恢复
     * @Param [client, taskType, clientPath, serverPath]
     * @return com.xtpt.disaster.common.PortalResult
     * @Date 9:20 2021/12/28
    **/
    @Override
    public PortalResult fileRecover(NodeInfo client, Integer taskType, String clientPath, String serverPath) {
        boolean res;

        String command = "scp" + " -r " + serverPath + " " + client.getNodeUsername() + "@" + client.getNodeIp() + ":" + clientPath;
        res = ShellExec.callShell(command);
        PortalResult result = new PortalResult();
        if (res)  {
            result.setStatus(StatusConst.SUCCESS);
            result.setMsg("文件备份成功");
            result.setData(command);
        }
        else {
            result.setStatus(StatusConst.ERROR);
            result.setMsg("文件备份失败");
            result.setData(command);
        }
        return result;
    }

    /**
     * @Author jack xin
     * @Method Name fileRecoverByAgent
     * @Desc 使用代理实现文件的恢复
     * @Param [taskInfo]
     * @return com.xtpt.disaster.common.PortalResult
     * @Date 9:21 2021/12/28
    **/
    @Override
    public PortalResult fileRecoverByAgent(TaskInfo taskInfo) {
        try {
            Long jobId = taskInfo.getJobDetailId();
            jobDetail = jobDetailService.getById(jobId);
            Long nodeId = taskInfo.getNodeId();
            NodeInfo nodeInfo = nodeInfoManageService.selectById(nodeId);

            if(jobDetail.getNodeId()==null)
                jobDetail.setNodeId(nodeId);

            fileCmdBuilder.initializeWithClientNode(nodeInfo);

            Integer dataType = taskInfo.getTaskFileType();

            DataTypeEnum dataTypeEnum = DataTypeEnum.getObject(dataType);
            String receiveUrl = String.format("/%s/receiver/%s",dataTypeEnum.getName().toLowerCase(Locale.ROOT), jobId);
            String callbackUrl = generator.urlGenerator(receiveUrl);
            fileCmdBuilder.setResultCallBackUrl(callbackUrl);
            Map<String, String> pathMap = fileCmdBuilder.fileRecover(jobDetail);
            // 将备份命令转化为json字符串
            String cmd = fileCmdBuilder.buildToJSONString();
            System.out.println("准备提交任务到客户端！");


            Date jobStartTime = TimeUtil.dateMaker();
            jobDetail.setJobStartTime(jobStartTime);

            // 保存job发出的cmd记录
            System.out.println(cmd);
            System.out.println(cmd.length());
            jobDetail.setJobCommand(cmd);
            jobDetail.setDataType(taskInfo.getTaskFileType());
            StringBuilder serverFilesPath = new StringBuilder();
            StringBuilder clientFilesPath = new StringBuilder();
            for (Map.Entry<String, String> entry : pathMap.entrySet()) {
                serverFilesPath.append(entry.getKey()).append(",");
                clientFilesPath.append(entry.getValue()).append(",");
            }

            Integer jobType = taskInfo.getTaskType();

            Integer jobBackupType = taskInfo.getTaskBackupType();

            Integer scheduleType = taskInfo.getTaskExectype();

            String jobName = taskInfo.getTaskName();

            //
            jobDetail.setDataType(dataType);
            //
            jobDetail.setJobType(jobType);
            //
            jobDetail.setJobBackupType(null);
            //
            jobDetail.setScheduleType(scheduleType);
            //
            jobDetail.setJobName(jobName);
            Long newJobId = IDGenerator.longid();

            jobDetail.setJobId(newJobId);

            // 将job记录存入表中
            PortalResult res = jobDetailService.insert(jobDetail);
            if (!res.isOK()) {
                return PortalResult.error("备份记录提交到作业表中失败");
            }

            // 将命令提交到代理端执行
            String agentUrl = agentUrlGenerator.generateUrl(nodeInfo);
            String postToClient = cn.hutool.http.HttpUtil.post(agentUrl, cmd);
            System.out.println("提交到客户端成功！");
            jobDetail.setJobResult(postToClient);
            jobDetailService.update(jobDetail);

            PortalResult portalResult = JSON.parseObject(postToClient, PortalResult.class);
            if (!portalResult.getStatus().equals(StatusConst.SUCCESS)) {
                return PortalResult.error("请求代理客户端失败！");
            }

        } catch (Exception e) {
            jobDetail.setJobResult(e.getMessage());
            jobDetail.setJobStatus(StatusConst.ERROR);
            jobDetailService.update(jobDetail);
            LogUtil.logger.error("文件恢复任务启动失败！");
            return PortalResult.error(e.getMessage());
        }
        return PortalResult.ok("文件恢复任务启动成功！");
    }
}
